<template>
  <div class="grid" style="gap: 12px">
    <GlassCard>
      <el-form label-position="top" label-width="auto">
        <div
          style="
            display: grid;
            grid-template-columns: minmax(190px, 1fr) 110px;
            gap: 12px;
            align-items: end;
          ">
          <el-form-item label="起始日期">
            <el-date-picker
              v-model="state.start"
              type="date"
              placeholder="选择日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD" />
          </el-form-item>
          <el-form-item label="间隔天数">
            <el-input-number
              v-model="state.days"
              :step="1"
              :min="0"
              style="width: 110px"
              controls-position="right" />
          </el-form-item>
        </div>

        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px">
          <el-form-item label="方向">
            <SegPills v-model="state.direction" :options="directionOptions" />
          </el-form-item>
          <el-form-item label="天数类型">
            <SegPills v-model="state.dayType" :options="dayTypeOptions" />
          </el-form-item>
        </div>

        <div class="date-result">
          <span class="label">结束日期：</span>
          <strong class="value">{{ resultDate }}</strong>
        </div>
        <div class="date-tips">
          <div class="tips-title">提示：</div>
          <div>
            · 本工具仅支持<span class="em">中国大陆</span
            >法定节假日与调休（数据源：Timor 假期接口）。
          </div>
          <div>· 计算规则为不包含起始日期（即从下一天开始计数）。</div>
        </div>
      </el-form>
    </GlassCard>
  </div>
</template>

<script setup lang="ts">
import {
  ElDatePicker,
  ElForm,
  ElFormItem,
  ElInputNumber,
  ElRadioButton,
  ElRadioGroup,
  ElSegmented
} from "element-plus"
import { computed, reactive, ref, watch } from "vue"

import { getCnCalendar } from "../scripts/services/holidays.js"
// @ts-ignore - SFC default export by Vue plugin
import GlassCard from "./ui/GlassCard.vue"
// @ts-ignore - SFC default export by Vue plugin
import SegPills from "./ui/SegPills.vue"

type DayType = "calendar" | "business"
type Direction = "forward" | "backward"

const state = reactive({
  start: new Date().toISOString().slice(0, 10),
  days: 5,
  dayType: "calendar" as DayType,
  direction: "forward" as Direction,
  country: "CN"
})

const dayTypeOptions = [
  { label: "自然日", value: "calendar" },
  { label: "工作日", value: "business" }
]

const directionOptions = [
  { label: "向后", value: "forward" },
  { label: "向前", value: "backward" }
]

function parseISO(dateStr: string): Date {
  const [y, m, d] = dateStr.split("-").map((s) => Number(s))
  return new Date(y, m - 1, d)
}

function formatISO(d: Date): string {
  const y = d.getFullYear()
  const m = String(d.getMonth() + 1).padStart(2, "0")
  const day = String(d.getDate()).padStart(2, "0")
  return `${y}-${m}-${day}`
}

async function addBusinessDays(
  start: Date,
  days: number,
  forward: boolean,
  country: string
): Promise<Date> {
  const year = start.getFullYear()
  const cal = await getCnCalendar(year)
  const holidaySet = new Set<string>(cal?.holidays || [])
  const workdaySet = new Set<string>(cal?.workdays || [])
  let remaining = days
  const step = forward ? 1 : -1
  let cur = new Date(start)
  while (remaining > 0) {
    cur.setDate(cur.getDate() + step)
    const iso = formatISO(cur)
    const isWeekend = cur.getDay() === 0 || cur.getDay() === 6
    // 优先使用补班标记；否则按“非周末且非节假日”为工作日
    const isBusiness =
      workdaySet.has(iso) || (!isWeekend && !holidaySet.has(iso))
    if (isBusiness) {
      remaining -= 1
    }
  }
  return cur
}

async function addDaysSmart(
  startISO: string,
  days: number,
  type: DayType,
  direction: Direction,
  country: string
): Promise<string> {
  const start = parseISO(startISO)
  const forward = direction === "forward"
  if (type === "calendar") {
    const d = new Date(start)
    d.setDate(d.getDate() + (forward ? days : -days))
    return formatISO(d)
  }
  const d = await addBusinessDays(start, days, forward, country)
  return formatISO(d)
}

const resultDate = ref<string>("--")

async function recompute() {
  if (!state.start || !Number.isFinite(state.days)) {
    resultDate.value = "--"
    return
  }
  resultDate.value = await addDaysSmart(
    state.start,
    state.days,
    state.dayType,
    state.direction,
    state.country
  )
}

watch(
  () => [
    state.start,
    state.days,
    state.dayType,
    state.direction,
    state.country
  ],
  () => {
    // fire and forget; resultDate will update when promise resolves
    void recompute()
  },
  { immediate: true }
)
</script>

<style scoped lang="less">
.date-result {
  background: #ffffff;
  border: 1px solid #e3edf5;
  border-radius: 12px;
  padding: 12px;
  font-size: 20px;
  display: flex;
  align-items: center;
  gap: 8px;
  text-align: left;
}
.date-result .label {
  color: #4b5b76;
  font-weight: 600;
}
.date-result .value {
  font-family:
    "Manrope",
    "Inter",
    "Roboto",
    system-ui,
    -apple-system,
    "Helvetica Neue",
    Arial,
    "Noto Sans",
    sans-serif;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  font-feature-settings:
    "tnum" 1,
    "lnum" 1;
  letter-spacing: 0.2px;
}

.date-tips {
  background: rgba(255, 255, 255, 0.85);
  border: 1px solid #e3edf5;
  border-radius: 12px;
  padding: 10px;
  text-align: left;
  line-height: 1.6;
  margin-top: 8px;
  font-size: 12px;
  color: #253858;
}
.date-tips .tips-title {
  font-weight: 600;
  color: #4b5b76;
}
.date-tips .em {
  color: #e04141;
  font-weight: 600;
}

/* Make radio buttons match pill theme */
:deep(.el-radio-group) {
  display: inline-flex;
  gap: 8px;
}
:deep(.el-radio-button) {
  margin: 0;
}
:deep(.el-radio-button__inner) {
  border-radius: 9999px !important;
  border: 1px solid rgba(36, 42, 66, 0.22);
  background: #d6e6ff;
  padding: 6px 14px;
  line-height: 20px;
  color: var(--fg);
}
:deep(.el-radio-button__inner:hover) {
  border-color: #3193e4;
}
:deep(.el-radio-button.is-active .el-radio-button__inner) {
  background: #ffffff !important;
  color: var(--fg);
  border-color: rgba(31, 76, 255, 0.55) !important;
  box-shadow: none;
}
/* Force override when using native checked */
:deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
  background: #ffffff !important;
  color: var(--fg) !important;
  border-color: rgba(31, 76, 255, 0.55) !important;
}

/* Style el-segmented like rounded pills */
:deep(.el-segmented) {
  border-radius: 9999px;
  background: #d6e6ff;
  padding: 2px;
  max-width: 100%;
}
:deep(.el-segmented__group) {
  gap: 4px;
}
:deep(.el-segmented__item) {
  border-radius: 9999px;
  color: var(--fg);
}
:deep(.el-segmented__item-label) {
  padding: 4px 0px;
  font-size: 14px;
}
:deep(.el-segmented__thumb) {
  border-radius: 9999px;
  background: #ffffff;
  border: 1px solid rgba(31, 76, 255, 0.55);
  box-shadow: none;
}

/* Selected state: keep rounded and show white text on blue thumb */
:deep(.seg-theme .el-segmented__thumb) {
  background: #1489fe;
  border-color: #1489fe;
}
:deep(.seg-theme .el-segmented__item-selected) {
  border-radius: 9999px 0 0 9999px !important;
  color: #ffffff !important;
}
:deep(.seg-theme .el-segmented__item.is-selected .el-segmented__item-label) {
  color: #ffffff !important;
}
</style>
